package de.reondo.jos.filters;

import java.util.regex.Pattern;

import org.jgrapht.GraphPath;
import org.jgrapht.alg.FloydWarshallShortestPaths;

import de.reondo.jos.ClassAnalyser;
import de.reondo.jos.ClassInfo;
import de.reondo.jos.ClassInfoDependencyEdge;

public class VertexFilter implements IFilter<ClassInfo> {

	private Pattern namePattern;
	private Pattern packagePattern;
	private int maxDistanceToRoot;
	private ClassAnalyser classAnalyser;
	private FloydWarshallShortestPaths<ClassInfo, ClassInfoDependencyEdge> shortestPaths;
	private ClassInfo rootClass;
	
	public VertexFilter(ClassAnalyser classAnalyser) {
		this.classAnalyser = classAnalyser;
		Pattern allPattern = Pattern.compile(".*");
		this.namePattern = allPattern;
		this.packagePattern = allPattern;
		this.maxDistanceToRoot = -1;
		rootClass = new ClassInfo(Object.class);
	}

	public Pattern getNamePattern() {
		return namePattern;
	}

	public void setNamePattern(Pattern namePattern) {
		this.namePattern = namePattern;
	}

	public void setNamePattern(String namePatternString) {
		this.namePattern = Pattern.compile(namePatternString);
	}

	public Pattern getPackagePattern() {
		return packagePattern;
	}

	public void setPackagePattern(Pattern packagePattern) {
		this.packagePattern = packagePattern;
	}

	public void setPackagePattern(String packagePatternString) {
		this.packagePattern = Pattern.compile(packagePatternString);
	}

	public int getMaxDistanceToRoot() {
		return maxDistanceToRoot;
	}

	public void setMaxDistanceToRoot(int maxDistanceToRoot) {
		this.maxDistanceToRoot = maxDistanceToRoot;
		if (maxDistanceToRoot >= 0 && shortestPaths == null) {
			shortestPaths = new FloydWarshallShortestPaths<ClassInfo, ClassInfoDependencyEdge>(
					classAnalyser.getGraph());
		}
	}

	@Override
	public boolean accept(ClassInfo cls) {
		boolean closeEnoughToRoot = true;
		if (maxDistanceToRoot >= 0 && !cls.equals(getRootClass())) {
			GraphPath<ClassInfo, ClassInfoDependencyEdge> path = shortestPaths
					.getShortestPath(getRootClass(), cls);
			if (path == null) {
				return false; // don't accept vertices not connected to root if
								// maxDistance is >= 0
			}
			closeEnoughToRoot = path.getEdgeList().size() <= maxDistanceToRoot;
		}
		return closeEnoughToRoot
				&& namePattern.matcher(cls.getName()).matches()
				&& packagePattern.matcher(cls.getPackage()).matches();
	}

    public ClassInfo getRootClass() {
        return rootClass;
    }

}
